#ifndef THREAD_EXECUTOR_H
#define THREAD_EXECUTOR_H

#include <map>
#include <vector>
#include "base/basic_types.h"
#include "base/callback.h"
#include "base/mutex.h"
#include "thread/thread.h"

class Callback;

class Executor {
 public:
  virtual int64 Add(Closure* callback) = 0;
  virtual bool Cancel(int64 id) = 0;
  virtual int64 AddAfter(int64 usec, Closure* callback) = 0;
  
 private:
  //Not threadsafe.
  //Executor* GetDefault();
  //static Executor* default_exectuor_;
};

class CallbackThread : public Thread {
 public:
  CallbackThread(Closure* callback);
  void set_done_callback(Closure* done_callback);
  virtual void Run();
 private:
  Closure* callback_;
  Closure* done_callback_;
};

struct CallbackState {
  int64 id;
  bool timed_callback_;
  CallbackThread* thread;
  Closure* callback;
  CallbackState()
      : id(-1),
        timed_callback_(false),
        thread(NULL),
        callback(NULL) {
  }
};

enum StatusChange {
  ADDED = 0,
  DONE = 1
};

class DefaultExecutor : public Executor {
 public:
  DefaultExecutor(int num_threads);
  ~DefaultExecutor();
  virtual int64 Add(Closure* callback);
  virtual int64 AddAfter(int64 usec, Closure* callback);
  virtual bool Cancel(int64 id);

 private:
  // This is exexuted in Timer thread.
  void MovePendingTimedClosure();
  void MarkDone(CallbackState* state);
  void StartRunnableClosure();
  std::map<int64, CallbackState*> pending_callbacks_;
  std::map<int64, std::map<int64, CallbackState*> > pending_timed_callbacks_;
  std::map<int64, CallbackState*> running_callbacks_;
  Mutex mutex_;
  pthread_mutex_t finalize_mutex_;
  pthread_cond_t finalize_cond_;
  int num_threads_;
  int current_id_;
  bool waiting_to_be_finalized_;
};

#endif
